package com.gxjtkyy.datadistributer.writer.rdbms.service;

import com.gxjtkyy.datadistributer.common.exception.ColumnParseException;
import com.gxjtkyy.datadistributer.writer.rdbms.vo.TableMetaData;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class TableMetaDataService {
   private static final Logger log = LoggerFactory.getLogger(TableMetaDataService.class);
   private final JdbcTemplate jdbcTemplate;

   @Cacheable(
      cacheNames = {"tableMetadata"},
      key = "#root.methodName+':'+#root.args[0]+'_'+#root.args[1]",
      sync = true
   )
   public TableMetaData getTableMetaData(String targetTableName, boolean columnCaseSensitive) {
      try {
         if (!columnCaseSensitive) {
            targetTableName = targetTableName.toUpperCase();
         }

         DataSource dataSource = (DataSource)Objects.requireNonNull(this.jdbcTemplate.getDataSource());
         Connection connection = dataSource.getConnection();

         TableMetaData var12;
         try {
            DatabaseMetaData metaData = connection.getMetaData();
            Set<String> keyColumnNames = new HashSet();
            ResultSet keys = metaData.getPrimaryKeys((String)null, (String)null, targetTableName);

            try {
               while(keys.next()) {
                  String name = keys.getString("COLUMN_NAME");
                  if (columnCaseSensitive) {
                     keyColumnNames.add(name);
                  } else {
                     keyColumnNames.add(name.toUpperCase());
                  }
               }
            } catch (Throwable var16) {
               if (keys != null) {
                  try {
                     keys.close();
                  } catch (Throwable var15) {
                     var16.addSuppressed(var15);
                  }
               }

               throw var16;
            }

            if (keys != null) {
               keys.close();
            }

            Map<String, String> columnTypeMap = new HashMap(16);
            int count = 0;
            ResultSet columns = metaData.getColumns((String)null, (String)null, targetTableName, (String)null);

            try {
               for(; columns.next(); ++count) {
                  String name = columns.getString("COLUMN_NAME");
                  String type = columns.getString("TYPE_NAME");
                  if (columnCaseSensitive) {
                     columnTypeMap.put(name, type);
                  } else {
                     columnTypeMap.put(name.toUpperCase(), type);
                  }
               }
            } catch (Throwable var17) {
               if (columns != null) {
                  try {
                     columns.close();
                  } catch (Throwable var14) {
                     var17.addSuppressed(var14);
                  }
               }

               throw var17;
            }

            if (columns != null) {
               columns.close();
            }

            if (columnTypeMap.keySet().size() != count) {
               throw new ColumnParseException("字段数量不一致，请检查大小写敏感配置是否正确");
            }

            Set<String> otherColumnNames = (Set)columnTypeMap.keySet().stream().filter((columnName) -> {
               return !keyColumnNames.contains(columnName);
            }).collect(Collectors.toSet());
            TableMetaData tableMetaData = new TableMetaData();
            tableMetaData.setTableName(targetTableName);
            tableMetaData.setKeyColumnNames(keyColumnNames);
            tableMetaData.setOtherColumnNames(otherColumnNames);
            Set<String> allColumnNames = (Set)Stream.of(keyColumnNames, otherColumnNames).flatMap(Collection::stream).collect(Collectors.toSet());
            tableMetaData.setAllColumnNames(allColumnNames);
            tableMetaData.setColumnTypes(columnTypeMap);
            var12 = tableMetaData;
         } catch (Throwable var18) {
            if (connection != null) {
               try {
                  connection.close();
               } catch (Throwable var13) {
                  var18.addSuppressed(var13);
               }
            }

            throw var18;
         }

         if (connection != null) {
            connection.close();
         }

         return var12;
      } catch (Throwable var19) {
         throw new ColumnParseException("字段数量不一致，请检查大小写敏感配置是否正确");
      }
   }

   public TableMetaDataService(final JdbcTemplate jdbcTemplate) {
      this.jdbcTemplate = jdbcTemplate;
   }
}
